package co.baiku.boot.youzan.push;

import co.baiku.boot.common.spring.SpringContext;
import co.baiku.boot.common.tools.EncryptTools;
import co.baiku.boot.common.tools.JsonTools;
import co.baiku.boot.common.tools.ServletTools;
import co.baiku.boot.common.tools.StringTools;
import co.baiku.boot.config.YouzanCloudConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.Map;

@Component
public class YouzanPushSubscriber implements InitializingBean {
    private Logger log = LoggerFactory.getLogger(YouzanPushSubscriber.class);
    // clientId, eventType, handler
    Map<String, Map<String, YouzanPushHandler>> handlerMap = new HashMap<>();

    @Override
    public void afterPropertiesSet() throws Exception {
        Map<String, YouzanPushHandler> subscribers = SpringContext.getBeansOfType(YouzanPushHandler.class);
        subscribers.forEach((k, v) -> {
            Map<String, YouzanPushHandler> youzanPushHandlerMap = handlerMap.computeIfAbsent(v.clientId(), k1 -> new HashMap<>());
            youzanPushHandlerMap.put(v.eventType(), v);
        });
    }

    public void subscribe(YouzanCloudConfig youzanCloudConfig, HttpServletRequest request, HttpServletResponse response) {
        String sign = request.getHeader("Event-Sign");
        String eventType = request.getHeader("Event-Type");
        String clientId = request.getHeader("Client-Id");
        String debug = request.getHeader("debug");
        try {
            String entity = ServletTools.getRequestBody(request);
            if (debug != null && "true".equalsIgnoreCase(debug)) {
                log.info("debug状态,跳过签名验证");
            } else {
                // 判断消息是否合法,md5方法可参考 https://www.youzanyun.com/support/faq/4215?qa_id=13065
                String ckSign = EncryptTools.md5(clientId + entity + youzanCloudConfig.getClientSecret());
                if (StringTools.isBlank(sign) || !ckSign.equals(sign)) {
                    ServletTools.printObjJson(response, fail());
                    return;
                }
            }
            //对于msg 先进行URI解码
            Map<String, YouzanPushHandler> youzanPushHandlerMap = handlerMap.get(clientId);
            if (youzanPushHandlerMap != null) {
                YouzanPushHandler youzanPushHandler = youzanPushHandlerMap.get(eventType);
                if (youzanPushHandler != null) {
                    boolean flag;
                    //如果Handler设定了处理消息
                    if (youzanPushHandler.parseMsg()) {
                        Map<String, Object> msgMap = JsonTools.jsonToMap(entity, false);
                        if (msgMap != null && msgMap.containsKey("msg")) {
                            String msg = "";
                            msg = msgMap.get("msg").toString();
                            msg = URLDecoder.decode(msg, "utf-8");
                            Map<String, Object> itemData = JsonTools.jsonToMap(msg, false);
                            String data;
                            if (itemData != null && itemData.containsKey("data")) {
                                data = (String) itemData.get("data");
                            } else {
                                data = URLDecoder.decode(entity, "utf-8");
                            }
                            flag = youzanPushHandler.execute(data);
                        } else {
                            entity = URLDecoder.decode(entity, "utf-8");
                            flag = youzanPushHandler.execute(entity);
                        }
                    } else {
                        //不处理消息,由Handler自己处理
                        flag = youzanPushHandler.execute(entity);
                    }
                    ServletTools.printObjJson(response, flag ? success() : fail());
                    return;
                }
            }
        } catch (Exception e) {
            log.error("[YouzanPushSubscriber - subscribe] 处理回调异常:" + e.getMessage(), e);
        }
    }

    public static void main(String[] args) throws UnsupportedEncodingException {
        String entity = "{\"address_detail\":\"普罗旺世北区\",\"city\":\"郑州市\",\"county\":\"金水区\",\"id\":58962840,\"is_optional_self_fetch_time\":1,\"is_super_store\":0,\"kdt_id\":46146039,\"lat\":34.827589,\"lon\":113.64065000000001,\"name\":\"测试自提点\",\"province\":\"河南省\",\"tel\":\"0371-68888888\",\"user_name\":\"吴帅飞\"}";
        Map<String, Object> msgMap = JsonTools.jsonToMap(entity, false);
        System.out.println(msgMap.get("id"));

    }

    private Map<String, Object> success() {
        Map<String, Object> res = new HashMap<>();
        res.put("code", 0);
        res.put("msg", "success");
        return res;
    }

    private Map<String, Object> fail() {
        Map<String, Object> res = new HashMap<>();
        res.put("code", 0);
        res.put("msg", "failed");
        return res;
    }

}
